// Copyright (c) Microsoft
// All rights reserved
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.

/// <summary>Copy from Iterator to non contiguous Array View</summary>
// RUN: %amp_device -D__GPU__ %s -m32 -emit-llvm -c -S -O3 -o %t.ll && mkdir -p %t
// RUN: %llc -march=c -o %t/kernel_.cl < %t.ll
// RUN: cat %opencl_math_dir/opencl_math.cl %t/kernel_.cl > %t/kernel.cl
// RUN: pushd %t && objcopy -B i386:x86-64 -I binary -O elf64-x86-64 kernel.cl %t/kernel.o && popd
// RUN: %cxxamp %link %t/kernel.o %s -o %t.out && %t.out

#include "../../CopyTestFlow.h"
#include "../../../../device.h"
#include <amp.h>
#include <deque>
#include <tuple>
const int RANK = 3;
typedef int DATA_TYPE;

using namespace Concurrency;

int ArrayViewOnCpu()
{
	accelerator_view cpu_av = accelerator(accelerator::cpu_accelerator).get_default_view();
	return CopyAndVerifyFromIteratorToNonContigArrayView<DATA_TYPE, RANK, std::vector>(cpu_av, access_type_none);
}

int ArrayViewOnGpu()
{
	accelerator gpu_acc = require_device_for<DATA_TYPE>();
	accelerator_view gpu_av = gpu_acc.get_default_view();
	
    int res;
	
	if(gpu_acc.get_supports_cpu_shared_memory())
	{
        //WLog() << "Accelerator " << gpu_acc.get_description() << " supports zero copy" << std::endl;
		
		// Set the default cpu access type for this accelerator
		gpu_acc.set_default_cpu_access_type(access_type_read_write);
		
        res &= (CopyAndVerifyFromIteratorToNonContigArrayView<DATA_TYPE, RANK, std::vector>(gpu_av, access_type_none));
        res &= (CopyAndVerifyFromIteratorToNonContigArrayView<DATA_TYPE, RANK, std::vector>(gpu_av, access_type_read));
        res &= (CopyAndVerifyFromIteratorToNonContigArrayView<DATA_TYPE, RANK, std::vector>(gpu_av, access_type_write));
        res &= (CopyAndVerifyFromIteratorToNonContigArrayView<DATA_TYPE, RANK, std::vector>(gpu_av, access_type_read_write));
	}
	else
	{
        res &= (CopyAndVerifyFromIteratorToNonContigArrayView<DATA_TYPE, RANK, std::vector>(gpu_av, access_type_none));
	}
	
	return res;
}

int main()
{
    int res = 1;
	
    res &= ArrayViewOnCpu();
    res &= ArrayViewOnGpu();
	
	return !res;
}

